var ElementTypes;
(function (ElementTypes) {
    ElementTypes["H1"] = "h1";
    ElementTypes["H2"] = "h2";
    ElementTypes["H3"] = "h3";
    ElementTypes["H4"] = "h4";
    ElementTypes["H5"] = "h5";
    ElementTypes["H6"] = "h6";
    ElementTypes["UL"] = "ul";
    ElementTypes["OL"] = "ol";
    ElementTypes["DIV"] = "div";
    ElementTypes["LI"] = "li";
    ElementTypes["P"] = "p";
    ElementTypes["Quota"] = "p";
    ElementTypes["CODE"] = "code";
})(ElementTypes || (ElementTypes = {}));
var DefaultConfig;
(function (DefaultConfig) {
    DefaultConfig["DefaultElementType"] = "p";
    DefaultConfig["DefaultContent"] = "<br>";
})(DefaultConfig || (DefaultConfig = {}));
var ClassName;
(function (ClassName) {
    ClassName["O_DN"] = "o-dn";
    ClassName["O_Quota"] = "o-quota";
    ClassName["O_H1"] = "o-h1";
    ClassName["O_H2"] = "o-h2";
    ClassName["O_H3"] = "o-h3";
    ClassName["O_H4"] = "o-h4";
    ClassName["O_H5"] = "o-h5";
    ClassName["O_H6"] = "o-h6";
    ClassName["O_UL"] = "o-ul";
    ClassName["O_OL"] = "o-ol";
    ClassName["O_DIV"] = "o-div";
    ClassName["O_LI"] = "o-li";
    ClassName["O_P"] = "o-p";
})(ClassName || (ClassName = {}));
var ImportID;
(function (ImportID) {
    ImportID["Container"] = "container";
    ImportID["Message"] = "message";
})(ImportID || (ImportID = {}));
var RedirectKey;
(function (RedirectKey) {
    RedirectKey["UP"] = "ArrowUp";
    RedirectKey["PAGEUP"] = "PageUp";
    RedirectKey["PAGEDOWN"] = "PageDown";
    RedirectKey["DOWN"] = "ArrowDown";
    RedirectKey["LEFT"] = "ArrowLeft";
    RedirectKey["RIGHT"] = "ArrowRight";
    RedirectKey["BACKSPACE"] = "Backspace";
    RedirectKey["ENTER"] = "Enter";
})(RedirectKey || (RedirectKey = {}));
var ElementFactory = /** @class */ (function () {
    function ElementFactory(type, content, className, element, uid) {
        this.container = null;
        this.element = null;
        this.type = null;
        this.content = null;
        this._uid = -1;
        this.className = null;
        this.typeList = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'p', 'div', 'pre'];
        this.preTypeList = [ElementTypes.UL, ElementTypes.OL];
        this.preTypeMap = new Map([
            [ElementTypes.OL, ElementTypes.LI],
            [ElementTypes.UL, ElementTypes.LI],
        ]);
        this.redirectKeyList = [
            RedirectKey.BACKSPACE, RedirectKey.DOWN, RedirectKey.UP, RedirectKey.LEFT, RedirectKey.RIGHT,
            RedirectKey.PAGEDOWN, RedirectKey.PAGEUP
        ];
        if (element) {
            this.element = element;
            this._uid = Number(uid);
            this.type = this.element.localName;
            this.content = this.element.innerText;
        }
        else {
            this.beforeCreateElement(type, content, className);
            this.createElement();
            this.afterCreateElement();
        }
    }
    Object.defineProperty(ElementFactory.prototype, "uid", {
        get: function () {
            return 'o' + this._uid;
        },
        enumerable: false,
        configurable: true
    });
    ElementFactory.prototype.getUid = function () {
        return 'o' + ++this._uid;
    };
    ;
    ElementFactory.newInstance = function (type, content, className, element, uid) {
        return new ElementFactory(type, content, className, element, uid);
    };
    ;
    ElementFactory.prototype.createElement = function () {
        if (this.typeList.includes(this.type)) {
            this.element = document.createElement(this.type);
            this.setInnerSpanHtml();
        }
        else {
            this.element = document.createElement('div');
            this.setInnerTypeSpanHtml();
        }
    };
    ElementFactory.prototype.beforeCreateElement = function (type, content, className) {
        this.type = type ? type : this.type;
        this.content = content ? content : this.content;
        this.className = className ? className : this.className;
    };
    ElementFactory.prototype.afterCreateElement = function () {
        this.element.id = this.getUid();
        this.element.contentEditable = 'true';
        this.className && (this.element.className = this.className);
    };
    ElementFactory.prototype.initAfterEnterCreateElement = function (newElement, content, className) {
        this.initAfterRedirectElement(newElement, content, className);
        this.afterCreateElement();
    };
    ElementFactory.prototype.initAfterRedirectElement = function (newElement, content, className) {
        this.type = ElementTypes[newElement.nodeName];
        this.element = newElement;
        this.content = content ? content : null;
    };
    ElementFactory.prototype.setOuterHtml = function (type, content, className) {
        // 设置样式
        if (className)
            this.element.className = className;
        className = null; // 必须清除内部样式
        this.element.outerHTML = this.element.outerHTML.toString()
            .replace(new RegExp("^<".concat(this.type)), function (match, pos, origins) {
            return '<' + (pos === 0 ? type : match);
        }).replace(new RegExp("".concat(this.type, ">$")), function (match, pos, origins) {
            return (pos === (origins.length - match.length) ? type : match) + '>';
        });
        this.beforeCreateElement(type, content, className);
    };
    ElementFactory.prototype.setInnerSpanHtml = function (content) {
        this.element.innerHTML = "<span>".concat(content ? content : this.content, "</span>");
    };
    ElementFactory.prototype.setInnerTypeSpanHtml = function (type, content) {
        type = type ? type : this.type;
        content = content ? content : this.content;
        // 单独给 type一个id
        this.element.innerHTML = "<".concat(type, " id=\"").concat(this.getUid(), "\"><span>").concat(content, "</span></").concat(type, ">");
    };
    ElementFactory.prototype.setInnerTypeSubSpanHtml = function (type, sub, content) {
        type = type ? type : this.type;
        content = content ? content : this.content;
        // 单独给 type一个id
        this.element.innerHTML = "<".concat(type, " id=\"").concat(this.getUid(), "\">\n                                    <").concat(sub, " id=\"").concat(this.getUid(), "\" >\n                                        <span>").concat(content, "</span>\n                                    </").concat(sub, ">\n                                  </").concat(type, ">");
    };
    ElementFactory.prototype.setInnerTypeDefaultHtml = function (type, content) {
        type = type ? type : this.type;
        content = content ? content : this.content;
        // 单独给 type一个id
        this.element.innerHTML = "<".concat(type, " id=\"").concat(this.getUid(), "\"><p><span>").concat(content, "</span></p></").concat(type, ">");
    };
    ElementFactory.prototype.attach = function (container, beforeNode, content) {
        this.container = container;
        if (!beforeNode) {
            container.appendChild(this.element);
        }
        else {
            container.insertBefore(this.element, beforeNode);
        }
    };
    return ElementFactory;
}());
var ContainerSetting = /** @class */ (function () {
    function ContainerSetting(instance, parser) {
        this.container = null;
        this.currentInstance = null;
        this.parser = null;
        this.readyToParse = false;
        this.readyParseType = null;
        this.readyParseClassName = null;
        this.readyParseLocal = null;
        this.newContent = null;
        this.isOnSubElement = false; // 是否在次级元素上
        this.container = instance.container;
        this.currentInstance = instance;
        this.parser = parser;
        this.initListener();
    }
    Object.defineProperty(ContainerSetting.prototype, "getSelection", {
        get: function () {
            return document.getSelection().anchorOffset - 1;
        },
        enumerable: false,
        configurable: true
    });
    Object.defineProperty(ContainerSetting.prototype, "currentAnchorParentElement", {
        /**
         * 获取当前选中位置的父节点
         */
        get: function () {
            return document.getSelection().anchorNode.parentElement;
        },
        enumerable: false,
        configurable: true
    });
    Object.defineProperty(ContainerSetting.prototype, "currentAnchorElement", {
        /**
         * 获取当前选中位置所在节点
         */
        get: function () {
            return document.getSelection().anchorNode;
        },
        enumerable: false,
        configurable: true
    });
    Object.defineProperty(ContainerSetting.prototype, "redirectCurrentElement", {
        /**
         * 重定向节点
         */
        get: function () {
            if (this.currentAnchorParentElement.id && this.currentAnchorParentElement.id !== ImportID.Container) {
                console.log('redirect currentAnchorParentElement');
                return this.currentAnchorParentElement;
            }
            else if (this.currentAnchorParentElement.id === ImportID.Container) {
                console.log('redirect currentAnchorElement');
                return this.currentAnchorElement;
            }
            else {
                if (this.currentAnchorParentElement.tagName === 'SPAN') {
                    var element = this.currentAnchorParentElement;
                    while (element.tagName === 'SPAN' && element.id != ImportID.Container) {
                        element = element.parentElement;
                    }
                    console.log('redirect', element);
                    return element;
                }
                console.log('redirect currentAnchorElement');
                return this.currentAnchorParentElement;
            }
        },
        enumerable: false,
        configurable: true
    });
    Object.defineProperty(ContainerSetting.prototype, "isChangeElement", {
        /**
         * 移动光标后 判断上一节点和当前节点是否不一样
         */
        get: function () {
            if (!(this.redirectCurrentElement).id) {
                return true;
            }
            else {
                return this.currentInstance.element.id !== (this.redirectCurrentElement).id;
            }
        },
        enumerable: false,
        configurable: true
    });
    ContainerSetting.prototype.initListener = function () {
        var _this = this;
        this.container.addEventListener('input', function (evInput) {
            // console.log('input')
        }, true);
        this.container.addEventListener('mouseup', function (evMouseup) {
            // 重定向到最新的父元素
            if (_this.isChangeElement) {
                _this.currentInstance.initAfterRedirectElement(_this.redirectCurrentElement);
                console.log('currentInstance: ', _this.redirectCurrentElement);
            }
        });
        window.addEventListener('keydown', function (evKeydown) {
            if (evKeydown.ctrlKey === true && (evKeydown.key === 's' || evKeydown.code === 'KeyS')) {
                // 浏览保存事件
                evKeydown.preventDefault();
                _this.onSaveDOM();
                return false;
            }
        }, false);
        this.container.addEventListener('keyup', function (evKeyup) {
            // console.log(evKeyup)
            if (evKeyup.key === ' ' || evKeyup.code === 'Space') {
                var _a = _this.parser
                    .parse(_this.currentInstance.element.innerText.slice(0, _this.getSelection).trim()), readyParseType = _a.readyParseType, className = _a.className;
                _this.readyParseType = readyParseType;
                _this.readyParseClassName = className;
                _this.readyToParse = !!_this.readyParseType;
                _this.onSpaceEvent();
                console.log('currentInstance: ', _this.currentInstance.element);
            }
            else if (evKeyup.key === 'Enter' || evKeyup.code === 'Enter') {
                _this.onEnterEvent(evKeyup);
                console.log('currentInstance: ', _this.currentInstance.element);
            }
            else if (_this.currentInstance.redirectKeyList.includes(evKeyup.key)) {
                if (_this.isChangeElement) {
                    _this.currentInstance.initAfterRedirectElement(_this.redirectCurrentElement);
                    console.log('currentInstance: ', _this.currentInstance.element);
                }
            }
            else {
                console.log(evKeyup.key);
            }
            // console.log(this.currentInstance.element.id);
        }, true);
        /**
         * 重写粘贴事件
         */
        this.container.addEventListener('paste', function (evPaste) {
            evPaste.preventDefault();
            var paste = evPaste.clipboardData.getData('text/plain');
            var selection = window.getSelection();
            if (!selection.rangeCount)
                return;
            selection.deleteFromDocument();
            selection.getRangeAt(0).insertNode(document.createTextNode(paste));
            selection.collapseToEnd();
        });
    };
    ContainerSetting.prototype.onEnterEvent = function (evKeyup) {
        if (!this.readyToParse) {
            // 在次级元素之中 并且
            if (this.isOnSubElement && this.currentInstance.preTypeList.includes(this.redirectCurrentElement.localName)) {
                console.log('内部换行');
                if (!this.currentInstance.element.innerText) {
                    // 如果本层级内容为空
                    this.currentInstance.initAfterEnterCreateElement(this.currentAnchorElement);
                }
                else {
                    this.currentInstance.initAfterEnterCreateElement(this.redirectCurrentElement);
                }
            }
            else {
                console.log('正常换行');
                // 重定向到最新的父元素
                this.isOnSubElement = false;
                this.currentInstance.initAfterEnterCreateElement(this.redirectCurrentElement);
                // 拿到换行点到行末尾的内容
                // const content = this.currentInstance.element.innerText.slice(this.getSelection + 1, );
                // this.currentInstance.initAfterEnterCreateElement(this.redirectCurrentElement);
            }
            // 改变节点html
            if (this.currentInstance.element.localName === ElementTypes.DIV) {
                // 正常换行时，从内部节点出来会自动生成一个div,这个时候应该设置为默认
                this.changeNodeHtml();
            }
            return;
        }
        console.log('解析换行');
        // 当前标签的解析
        // 等到回车事件再执行的事件
        this.newContent = this.currentInstance.element.innerText.slice(this.readyParseLocal); // 拿到yyy
        // 根据解析结果 改变当前节点
        this.changeNodeHtml(this.readyParseType, this.newContent, this.readyParseClassName);
        // 重定向到最新的节点（回车后）
        this.currentInstance.initAfterEnterCreateElement(this.redirectCurrentElement);
        // 给默认生成的节点设置默认值
        this.changeNodeHtml();
        this.afterSetOuterHtml();
    };
    ContainerSetting.prototype.onSpaceEvent = function () {
        if (!this.readyToParse) {
            return;
        }
        this.readyParseLocal = this.getSelection + 1; // 解析的位置 xxx {local}yyy 取到空格位置
        var isPreType = this.currentInstance.preTypeList.includes(this.readyParseType); // 判断是否是预设的几种标签
        if (isPreType) {
            // console.log('解析空格')
            // console.log('readyParseType', this.readyParseType);
            // console.log(this.newContent)
            this.newContent = this.currentInstance.element.innerText.slice(this.readyParseLocal); // 拿到yyy
            if (this.isOnSubElement) {
                // 在次级元素中解析 新的元素
                // 重定向到最新的节点
                this.currentInstance.initAfterEnterCreateElement(this.redirectCurrentElement);
                // 根据解析结果 改变当前节点
                console.log('isOnSubElement: ', this.currentInstance.element);
                this.currentInstance.setInnerTypeSubSpanHtml(this.readyParseType, this.currentInstance.preTypeMap.get(this.readyParseType), this.newContent.length > 0 ? this.newContent : DefaultConfig.DefaultContent);
                // 重定向 到类似于 li的元素之上
                this.currentInstance.element = document.getElementById(this.currentInstance.uid);
                this.isOnSubElement = true; // 次级元素
                this.readyToParse = false;
                return;
            }
            // console.log('newContent', this.newContent.length > 0 ? this.newContent : ' ');
            this.currentInstance.setOuterHtml(this.readyParseType, null, this.readyParseClassName);
            // 重定向
            this.currentInstance.element = document.getElementById(this.currentInstance.element.id);
            // 设置 类似于 ul的内部 li元素
            this.currentInstance.setInnerTypeSpanHtml(this.currentInstance.preTypeMap.get(this.readyParseType), this.newContent.length > 0 ? this.newContent : DefaultConfig.DefaultContent);
            // 重定向 到类似于 li的元素之上
            this.currentInstance.element = document.getElementById(this.currentInstance.uid);
            this.isOnSubElement = true; // 次级元素
            this.readyToParse = false;
            this.readyParseType = null;
        }
    };
    ContainerSetting.prototype.changeNodeHtml = function (type, content, className) {
        type = (!type) ? DefaultConfig.DefaultElementType : type;
        content = (!content) ? DefaultConfig.DefaultContent : content;
        className = (!className) ? null : className;
        // 重组当前节点为默认标签内容
        this.currentInstance.setOuterHtml(type, null, className);
        // 重定向
        this.currentInstance.element = document.getElementById(this.currentInstance.element.id);
        // 添加span
        this.currentInstance.setInnerSpanHtml(content);
    };
    ContainerSetting.prototype.afterSetOuterHtml = function () {
        this.readyToParse = false;
        this.readyParseType = null;
        this.readyParseClassName = null;
        this.readyParseLocal = null;
    };
    ContainerSetting.prototype.onSaveDOM = function () {
        localStorage.setItem('OMG-save-all', this.container.innerHTML.toString());
        localStorage.setItem('OMG-save-id', this.currentInstance._uid + '');
        var message = document.getElementById('message');
        message.style.display = 'block';
        message.innerHTML = '保存成功';
        setTimeout(function () {
            message.style.display = 'none';
        }, 1000);
    };
    return ContainerSetting;
}());
var TextParserIm = /** @class */ (function () {
    function TextParserIm() {
    }
    TextParserIm.prototype.parse = function (text) {
        this.text = text;
        console.log('text', text);
        if (this.isHeader()) {
            console.log('header');
            return { readyParseType: ElementTypes['H' + text.length], className: ClassName['O_H' + text.length] };
        }
        else if (this.isUL()) {
            return { readyParseType: ElementTypes.UL, className: ClassName.O_UL };
        }
        else if (this.isOL()) {
            return { readyParseType: ElementTypes.OL, className: ClassName.O_OL };
        }
        else if (this.isQuote()) {
            return { readyParseType: ElementTypes.Quota, className: ClassName.O_Quota };
        }
        return { readyParseType: null, className: null };
    };
    TextParserIm.prototype.isHeader = function () {
        return /^#{1,6}$/.test(this.text);
    };
    TextParserIm.prototype.isUL = function () {
        return /^-$/.test(this.text);
    };
    TextParserIm.prototype.isOL = function () {
        return /^\d.$/.test(this.text);
    };
    TextParserIm.prototype.isQuote = function () {
        return /^>$/.test(this.text);
    };
    return TextParserIm;
}());
var Main = /** @class */ (function () {
    function Main() {
        var container = document.getElementById('container');
        container.focus();
        var item = localStorage.getItem('OMG-save-all');
        var instance;
        if (item) {
            container.innerHTML = item;
            var child = container.lastElementChild;
            if (child.innerHTML === '<br>') {
                child.innerHTML = "<span><br></span>";
            }
            var uid = localStorage.getItem('OMG-save-id');
            instance = ElementFactory.newInstance(null, null, null, document.getElementById(child.id), uid);
        }
        else {
            instance = ElementFactory.newInstance(ElementTypes.P, '李泽江你好！', null);
        }
        instance.attach(container);
        var parser = new TextParserIm();
        var containerSetting = new ContainerSetting(instance, parser);
    }
    return Main;
}());
var main = new Main();
